/************************************************
 * Author       :   XXY
 * Blog         :   https://www.cnblogs.com/jzyl
 * Gitee        :   https://gitee.com/xiaobaichong
 * Email        :   1047185209@QQ.com
 * FileName     :   EventEmitter.cs
 * CreateData   :   2024/5/28 23:09:55
 * UnityVersion :   2021.3.30f1c1
 * Description  :   事件触发与事件监听器功能的封装
************************************************/

using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using UnityEngine;

namespace Main
{
    /// <summary>
    /// 事件触发与事件监听器功能的封装
    /// </summary>
    /// <typeparam name="Key">绑定类型</typeparam>
    public class EventEmitter<Key>
    {
        private ConcurrentDictionary<Key, Action> _events = new ConcurrentDictionary<Key, Action>();    // 需要手动移除
        private ConcurrentDictionary<Key, Action> _once = new ConcurrentDictionary<Key, Action>();      // 触发自动移除

        /// <summary>
        /// 事件注册
        /// </summary>
        public void On(Key key, Action action)
        {
            if (_events.ContainsKey(key))
            {
                _events[key] += action;
            }
            else
            {
                _events[key] = action;
            }
        }
        /// <summary>
        /// 单次事件注册
        /// </summary>
        public void Once(Key key, Action action)
        {
            if (_once.ContainsKey(key))
            {
                _once[key] += action;
            }
            else
            {
                _once[key] = action;
            }
        }

        /// <summary>
        /// 移除所有事件
        /// </summary>
        public void RemoveAllListeners()
        {
            _events.Clear();
            _once.Clear();
        }
        /// <summary>
        ///  移除指定注册事件
        /// </summary>
        public void RemoveListener(Key key, Action action)
        {
            if (_events.ContainsKey(key)) _events[key] -= action;
            if (_once.ContainsKey(key)) _once[key] -= action;
        }

        /// <summary>
        /// 触发事件
        /// </summary>
        public void Emit(Key key)
        {
            if (_events.ContainsKey(key)) _events[key]?.Invoke();
            if (_once.ContainsKey(key)) _once[key]?.Invoke();
            _once[key] = null;
        }
    }

    /// <summary>
    /// 事件触发与事件监听器功能的封装
    /// </summary>
    /// <typeparam name="Key">绑定类型</typeparam>
    /// <typeparam name="Param">参数类型</typeparam>
    public class EventEmitter<Key, Param>
    {
        private ConcurrentDictionary<Key, Action<Param>> _events = new ConcurrentDictionary<Key, Action<Param>>();    // 需要手动移除
        private ConcurrentDictionary<Key, Action<Param>> _once = new ConcurrentDictionary<Key, Action<Param>>();      // 触发自动移除

        /// <summary>
        /// 事件注册
        /// </summary>
        public void On(Key key, Action<Param> action)
        {
            if (_events.ContainsKey(key))
            {
                _events[key] += action;
            }
            else
            {
                _events[key] = action;
            }
        }
        /// <summary>
        /// 单次事件注册
        /// </summary>
        public void Once(Key key, Action<Param> action)
        {
            if (_once.ContainsKey(key))
            {
                _once[key] += action;
            }
            else
            {
                _once[key] = action;
            }
        }

        /// <summary>
        /// 移除所有事件
        /// </summary>
        public void RemoveAllListeners()
        {
            _events.Clear();
            _once.Clear();
        }
        /// <summary>
        ///  移除指定注册事件
        /// </summary>
        public void RemoveListener(Key key, Action<Param> action)
        {
            if (_events.ContainsKey(key)) _events[key] -= action;
            if (_once.ContainsKey(key)) _once[key] -= action;
        }

        /// <summary>
        /// 触发事件
        /// </summary>
        public void Emit(Key key, Param data)
        {
            if (_events.ContainsKey(key)) _events[key]?.Invoke(data);
            if (_once.ContainsKey(key)) _once[key]?.Invoke(data);
            _once[key] = null;
        }
    }

    /// <summary>
    /// 事件触发与事件监听器功能的封装
    /// </summary>
    /// <typeparam name="Key">绑定类型</typeparam>
    /// <typeparam name="This">实例化类型</typeparam>
    /// <typeparam name="Param">参数类型</typeparam>
    public class EventEmitter<Key, This, Param>
    {
        private ConcurrentDictionary<Key, Action<This, Param>> _events = new ConcurrentDictionary<Key, Action<This, Param>>();    // 需要手动移除
        private ConcurrentDictionary<Key, Action<This, Param>> _once = new ConcurrentDictionary<Key, Action<This, Param>>();      // 触发自动移除

        /// <summary>
        /// 事件注册
        /// </summary>
        public void On(Key key, Action<This, Param> action)
        {
            if (_events.ContainsKey(key))
            {
                _events[key] += action;
            }
            else
            {
                _events[key] = action;
            }
        }
        /// <summary>
        /// 单次事件注册
        /// </summary>
        public void Once(Key key, Action<This, Param> action)
        {
            if (_once.ContainsKey(key))
            {
                _once[key] += action;
            }
            else
            {
                _once[key] = action;
            }
        }

        /// <summary>
        /// 移除所有事件
        /// </summary>
        public void RemoveAllListeners()
        {
            _events.Clear();
            _once.Clear();
        }
        /// <summary>
        ///  移除指定注册事件
        /// </summary>
        public void RemoveListener(Key key, Action<This, Param> action)
        {
            if (_events.ContainsKey(key)) _events[key] -= action;
            if (_once.ContainsKey(key)) _once[key] -= action;
        }

        /// <summary>
        /// 触发事件
        /// </summary>
        public void Emit(Key key, This _this, Param data)
        {
            if (_events.ContainsKey(key)) _events[key]?.Invoke(_this, data);
            if (_once.ContainsKey(key)) _once[key]?.Invoke(_this, data);
            _once[key] = null;
        }
    }
}
